" vim: ft=vim
" Test getattr()
"
Before;
let X = object#class('X')

" Dealing with plain dict. No hooks.
Execute(Gets an attribute from a plain dict);
let foo = { 'name': 'foo' }
AssertEqual object#getattr(foo, 'name'), 'foo'


Execute(Throws AttributeError from a plain dict);
let foo = { 'age': 11 }
AssertThrows call object#getattr(g:foo, 'name')
Assert g:vader_exception =~# 'AttributeError'


Execute(Returns default from a plain dict);
let bar = { 'name' : 'bar' }
AssertEqual object#getattr(bar, 'age', 11), 11
AssertEqual object#getattr(bar, 'friends', []), []


" WrongType sanity checks.
Execute(throws WrongType when some of its required arguments are not of correct type);
AssertThrows call object#getattr(1, 'name')
Assert g:vader_exception =~# 'WrongType'

AssertThrows call object#getattr({}, [])
Assert g:vader_exception =~# 'WrongType'

AssertThrows call object#getattr(1, [])
Assert g:vader_exception =~# 'WrongType'

" Combination of __getattr__, __getattribute__ and default.

" single __getattribute__.
Execute(__getattribute__ returns);
function! X.__getattribute__(key)
  return 1
endfunction

let x = object#new(X)
AssertEqual object#getattr(x, 'foo'), 1


Execute(__getattribute__ throws);
function! X.__getattribute__(key)
  throw object#AttributeError()
endfunction

AssertThrows call object#getattr(object#new(g:X), 'foo')
Log g:vader_exception
Assert g:vader_exception =~# 'AttributeError'


" __getattribute__ with __getattr__.
Execute(__getattribute__ wins over __getattr__);
function! X.__getattribute__(key)
  return 1
endfunction
function! X.__getattr__(key)
  return 0
endfunction
AssertEqual object#getattr(object#new(g:X), 'foo'), 1


Execute(__getattribute__ loses to  __getattr__);
function! X.__getattribute__(key)
  throw object#AttributeError()
endfunction
function! X.__getattr__(key)
  return 0
endfunction
AssertEqual object#getattr(object#new(g:X), 'foo'), 0


Execute(Both lose);
function! X.__getattribute__(key)
  throw object#AttributeError()
endfunction
function! X.__getattr__(key)
  throw object#AttributeError()
endfunction
AssertThrows call object#getattr(object#new(g:X), 'foo')
Assert g:vader_exception =~# 'AttributeError'


" Default and __getattr__.
Execute(__getattr__ wins over default);
function! X.__getattr__(key)
  return 1
endfunction

AssertEqual object#getattr(object#new(X), 'foo', 0), 1


Execute(__getattr__ loses to default);
function! X.__getattr__(key)
  throw object#AttributeError()
endfunction

AssertEqual object#getattr(object#new(X), 'foo', 0), 0


Execute(Fall all the way to default);
function! X.__getattribute__(key)
  throw object#AttributeError()
endfunction
function! X.__getattr__(key)
  throw object#AttributeError()
endfunction
AssertEqual object#getattr(object#new(X), 'foo', 0), 0
